package org.sheep;

import java.io.IOException;

import org.sheep.R;
import org.sheep.sprite.LaneManager;
import org.sheep.world.WorldMap;
import org.sheep.world.WorldMapFactory;
import org.xmlpull.v1.XmlPullParserException;

import android.content.Context;
import android.content.res.TypedArray;
import android.graphics.Canvas;
import android.os.Bundle;
import android.util.AttributeSet;
import android.util.Log;
import android.view.SurfaceHolder;
import android.view.SurfaceView;

public class GameView extends SurfaceView implements SurfaceHolder.Callback  {
	private GameThread thread;
	
	public GameView(Context context, AttributeSet attrs) {
		super(context, attrs);
		
    SurfaceHolder holder = getHolder();
    holder.addCallback(this);
    
    thread = new GameThread(holder, context, attrs, this);
	}
	
	public GameThread getThread() {
	  return thread;
	}

	public void surfaceChanged(SurfaceHolder holder, int format, int width,
	       int height) {
		// TODO Auto-generated method stub
    thread.resize(width, height);
	}

	public void surfaceCreated(SurfaceHolder holder) {
		// TODO Auto-generated method stub
	  //resize();
    thread.start();
		
	}

	public void surfaceDestroyed(SurfaceHolder holder) {
		// TODO Auto-generated method stub
		
	}
	
	public class GameThread extends Thread{
	  private int width;
	  private int height;
	  
	  private int viewWidth;
	  private int viewHeight;
	  
	  private SurfaceView view;
	  
	  private WorldMap map;
    private LaneManager lanes;
    private SpawnManager sm;
	  
	  //Game States
	  public final static int STATE_WIN = 0;
	  public final static int STATE_LOSE = 1;
	  public final static int STATE_PAUSE = 2;
	  public final static int STATE_RUNNING = 3;
	  
	  private SurfaceHolder holder;
	  private Context context;
	  
	  //becomes true after initialization
	  private boolean running = false;
	  
	  public GameThread(SurfaceHolder holder, Context context, AttributeSet attrs, SurfaceView view) {
	    TypedArray a = context.obtainStyledAttributes(attrs, R.styleable.GameView);
      width = a.getInt(R.styleable.GameView_width, 12);
      height = a.getInt(R.styleable.GameView_height, 12);
      a.recycle();
      
      try {
        map = new WorldMapFactory(width, height, context).build();
      } catch (XmlPullParserException e) {
        e.printStackTrace();
      } catch (IOException e) {
        e.printStackTrace();
      }
      
      lanes = new LaneManager(width, height, map.getTileWidth(), 0);
      
      try {
        sm = new SpawnManagerFactory(lanes).build();
      } catch (XmlPullParserException e) {
        e.printStackTrace();
      } catch (IOException e) {
        e.printStackTrace();
      }

      this.view = view;
      
      this.holder = holder;
      this.context = context;
	  }
	  
    @Override
    public void run() {
        Log.i("GameThread", "Before draw");

        map.setSize(width, height, view.getMeasuredWidth(), view.getMeasuredHeight(), context);
        lanes.setSize(width, height, view.getMeasuredWidth(), view.getMeasuredWidth(), context);
        
        sm.nextWave();
        while (running) {
            Canvas c = null;
            try {
                c = holder.lockCanvas(null);
                synchronized (holder) {
                  //draw and update physics
                  map.draw(c);
                  
                  sm.update();
                  lanes.update();
                  lanes.draw(c);
                }
            } finally {
                //in case of an exception the holder has to be unlocked
                //to ensure an consistent state
                if (c != null) {
                    holder.unlockCanvasAndPost(c);
                }
            }
        }
    }
	  
	  public void pause() {
	    
	  }
	  
	  public void ready() {
	    running = true;
	  }

    public void restore(Bundle savedInstanceState) {
      // TODO Auto-generated method stub
      
    }

    public void save(Bundle outState) {
      // TODO Auto-generated method stub
      
    }

    public void save() {
      // TODO Auto-generated method stub
      
    }
    
    // Callback invoked when the surface dimensions change
    public void resize(int viewWidth, int viewHeight) {
        synchronized (holder) {
            this.viewWidth = viewWidth;
            this.viewHeight = viewHeight;
            
            map.setSize(width, height, viewWidth, viewHeight, context);
            lanes.setSize(width, height, viewWidth, viewHeight, context);
        }
    }
	}

}
